def find_nearby_profiles(cls, me, count):
    """Finds and returns nearby profiles, up to count or until or scope is reached.

    Returns:
      List of users, nearest myself first, with no duplicates
    """

    log = me.log
    log.debug('%r looking for %d profiles', me, count)

    debugging = False
    if log.getEffectiveLevel() == logging.DEBUG:
      log.debug('Extra debugging code enabled')
      debugging = True

    # Store the profiles which match the age filter. Keys are profile entities, values are distances from me.
    found_profiles = {}

    # For analysis, store various other profiles which don't belong in the cascade but which were involved in the query.
    discarded_profile_keys = { 'my favorite': set(), 'i block you': set(), 'you block me': set() }

    # Also remember the set of all users ever seen so they don't need to be fetched twice.
    seen_profile_keys = set()

    for geobox_level, params in enumerate(GEOBOX_CONFIGS):
      resolution, slice, unused = params
      box = geobox.compute(me.location.lat, me.location.lon, resolution, slice)
      log.debug("Searching for box=%s at resolution=%s, slice=%s", box, resolution, slice)

      # XXX: No memcache for now
      key_name = "geobox_search:" + box # + "-" + str(me.ageMin) + "-" + str(me.ageMax)
      #results = memcache.get(key_name)
      results = None

      if results:
        log.debug('memcache hit: %s', key_name)
      else:
        log.debug("memcache miss: %s", key_name)

        log.debug('Attempting to fetch 1000 visible ProfileLocation keys for %s', box)
        query = cls.all(keys_only=True).filter('visible =', True).filter('geoboxes =', box)
        if me.metadata.search_online_only:
          log.debug('...where online = True')
          query.filter('online =', True)
        if me.metadata.ageMin > 0:
          log.debug('...where age >= %d', me.metadata.ageMin)
          query.filter('age >=', me.metadata.ageMin)
        if me.metadata.ageMax > 0:
          log.debug('...where age <= %d', me.metadata.ageMax)
          query.filter('age <=', me.metadata.ageMax)

        location_keys = query.fetch(1000)
        log.debug('Fetch complete')

        log.debug('Found %d location keys', len(location_keys))
        last_cycle = False
        if len(location_keys) > 750:
          log.warn('%d keys found for geobox %s resolution=%s slice=%s', len(location_keys), box, resolution, slice)
          last_cycle = True

        if len(location_keys) > 28:
          log.debug('Storing in memcache: %s', key_name)
          # memcache.add(key=key_name, value=location_keys, time=60*20)

      profile_keys = [x.parent() for x in location_keys]
      del location_keys

      profile_keys = [x for x in profile_keys if x != me.key()]
      log.debug('Pruned myself: %d keys remaining', len(profile_keys))

      # Remember all keys that are to be discarded later.
      discarded_profile_keys['my favorite'].update( [x for x in profile_keys if x in me.favorite_profile_keys])
      discarded_profile_keys['i block you'].update( [x for x in profile_keys if x in me.blocked_profile_keys])
      discarded_profile_keys['you block me'].update([x for x in profile_keys if x in me.profile_keys_blocking_me])

      profile_keys = [x for x in profile_keys if x not in me.favorite_profile_keys]
      log.debug('Pruned favorites: %d keys remaining', len(profile_keys))

      profile_keys = [x for x in profile_keys if x not in me.blocked_profile_keys]
      log.debug('Pruned blocks: %d keys remaining', len(profile_keys))

      profile_keys = [x for x in profile_keys if x not in me.profile_keys_blocking_me]
      log.debug('Pruned those blocking me: %d keys remaining', len(profile_keys))

      profile_keys = [x for x in profile_keys if x not in seen_profile_keys]
      log.debug('Pruned those already seen: %d keys remaining', len(profile_keys))

      # TODO: Is it necessary to fetch these inside the loop. Why not build up enough keys
      # and then load them outside this loop since the age filter is now in the query.

      for profile in db_get_iterator(profile_keys, chunk_size=400, cached=True):
        if not profile:
          log.error('Got a null profile')
        else:
          seen_profile_keys.add(profile.key())

          if not profile.online_worthy:
            log.warn('%r was in the results but is not online worthy; signing off', profile)
            profile.log = log
            profile.signoff(with_transaction=False)
            continue

          found_profiles[profile] = profile.distance_to(me)

      # TODO: cache
      # memcache.set_multi(profiles, time=45*60, key_prefix='Profile:')

      if geobox_level >= 15:
        log.info('Candidate lonely user (%d): %r', geobox_level, me)

      log.debug('Found %d of %d required profiles', len(found_profiles), count)
      if len(found_profiles) >= count:
        break
      if last_cycle:
        log.debug('Early exit due to checking many people')
        break

    #
    # End geobox loop
    #

    if 'd046af6ee7c659d2eb57d4aed67acbc75bf06e64' in [x.key().name() for x in found_profiles.keys()]:
      log.debug('Joel is in the set')
    else:
      log.debug('Joel IS NOT in the set')

    def compare_profile_distances(a, b):
      return cmp(a[1], b[1])

    # TODO: Warn about extremely distant profiles (distance > 12000).
    profiles = sorted(found_profiles.iteritems(), cmp=compare_profile_distances)
    profiles = profiles[:count]
    profiles = [x[0] for x in profiles] # Throw out the distances.
    log.debug("Profiles sorted and sliced")

    # Possibly record what happened for analysis.
    CascadeSequence.record_cascade_for(me, profiles, discarded_profile_keys)

    if debugging:
      log.debug('Found %d profiles:', len(profiles))
      for profile in profiles:
        log.debug('%r distance=%s', profile, profile.distance_to(me))

    return profiles